#pragma once
#include "Sock.hpp"
#include <functional>
#include <vector>
#include <pthread.h>

namespace ns_tcpserver
{
    using func_t = std::function<void(int)>;
    class TcpServer; // 提前声明，使得ThreadData可以用TcpServer.然后TcpServer也可以用ThreadData
    class ThreadData // 当结构体使用
    {
    public:
        ThreadData(int sock, TcpServer *server) : sock_(sock), server_(server)
        {
        }
        ~ThreadData() {}

    public:
        int sock_;
        TcpServer *server_;
    };

    class TcpServer // 服务端，今天做到了网络功能(绑定),和服务功能(处理)的解耦
    {
    private:
        static void *ThreadRoutine(void *args)
        {
            pthread_detach(pthread_self());
            ThreadData *td = static_cast<ThreadData *>(args);
            td->server_->Excute(td->sock_);
            close(td->sock_); // 执行完
            delete td;        // 释放线程数据
            return nullptr;
        }

    public:
        TcpServer(const uint16_t &port, const std::string &ip = "0.0.0.0") : // 服务端构造函数,初始化接客员套接字
                                                                             listensock_(-1)
        {
            // 1.创建套接字-相当于将文件描述符指向这个文件
            listensock_ = sock_.Socket();

            // 2.绑定服务端port,ip与sock(listensock)
            sock_.Bind(listensock_, port, ip);

            // 3.设listensock服务员为监听状态，可被链接
            sock_.Listen(listensock_);
        }
        void BindService(func_t func)
        { // 4.绑定任务给服务端
            funcs.push_back(func);
        } 

        void Excute(int sock) // 7.执行任务
        {
            for (auto &f : funcs) // 遍历执行服务函数-一个线程不断遍历执行任务
            {
                f(sock);//在这里面处理数据,并发到serversock中，让客户端读取
            }
        }
        void Start()
        {
            for (;;)
            {
                std::string clientip;
                uint16_t clientport;
                //5.listensock派发serversock给客户端
                int sock = sock_.Accept(listensock_, &clientip, &clientport); // 获取新链接,派发服务员来处理客户端的数据

                logMessage(NORMAL, "create new link success, sock: %d", sock);

                pthread_t tid;
                //6.准备开始处理任务
                ThreadData *td = new ThreadData(sock/*serversock*/, this);
                pthread_create(&tid, nullptr, ThreadRoutine, td); // 把服务端，和要处理的数据，传给线程进行操作
            }
        }

        ~TcpServer()
        {
            if (listensock_ >= 0)
                close(listensock_);
        }

    private:
        int listensock_;
        Sock sock_;
        // func_t func_;//服务函数
        std::vector<func_t> funcs;                     // 一组服务函数
        std::unordered_map<std::string, func_t> func_; // 每个服务的名字,绑定一个服务端就加入一个服务名称
    };
};